from fastapi import Depends
from sqlalchemy import not_

from app.business.milvus_index import MilvusIndexCreateBiz
from app.business.user_collection import UserCollectionCreateBiz
from app.datatype.user import (
    User,
    UserDetailMdl,
    UserListMdl,
    UserCreateMdl,
    UserUpdateMdl,
    UserDeleteMdl,
    UserLoginMdl,
    UserTokenMdl,
)
from app.datatype.user_collection import UserCollection
from app.initializer import g
from app.utils import auth, db_async
from app.middleware.auth import JWTUser, get_current_user


class UserDetailBiz(UserDetailMdl):

    async def detail(self):
        async with g.db_async_session() as session:
            data = await db_async.query_one(
                session=session,
                model=User,
                fields=self.response_fields(),
                filter_by={"id": self.id},
            )
            return data


class UserListBiz(UserListMdl):

    async def lst(self, current_user):
        custom_filters = None
        print("current_user:", current_user)
        if current_user.role == 1:
            # 普通用户
            return None, 0
        if current_user.role == 2:
            # 管理员
            custom_filters = [not_(User.role == 3)]
        if current_user.role == 3:
            # 超级管理员
            custom_filters = None

        async with g.db_async_session() as session:
            if self.find == "" or self.find is None:
                fuzzy = None
            else:
                fuzzy = {"collections": self.find, "name": self.find}
            data = await db_async.query_all(
                session=session,
                model=User,
                custom_filters=custom_filters,
                fields=self.response_fields(),
                page=self.page,
                fuzzy=fuzzy,
                size=self.size,
            )
            total = await db_async.query_total(session, User,
                                               fuzzy={"collections": self.find, "name": self.find},
                                               custom_filters=custom_filters,
                                               )
            return data, total


class UserCreateBiz(UserCreateMdl):

    async def create(self):

        async with g.db_async_session() as session:
            userId =  await db_async.create(
                session=session,
                model=User,
                data={
                    "name": self.name,
                    "phone": self.phone,
                    "age": self.age,
                    "gender": self.gender,
                    "password": auth.hash_password(self.password),
                    "jwt_key": auth.gen_jwt_key(),
                    "role": self.role if self.role else 1,  # 默认角色为普通用户
                    "collections": self.collections if self.collections else "",
                },
                filter_by={"phone": self.phone},
            )
            userCollectionBiz = UserCollectionCreateBiz()

            if self.milvusIndexIdList and len(self.milvusIndexIdList) > 0:
                for milvus_index_id in self.milvusIndexIdList:
                    userCollectionBiz.user_id = userId
                    userCollectionBiz.milvus_index_id = milvus_index_id
                    await userCollectionBiz.create()

            milvus_index_biz = MilvusIndexCreateBiz()
            milvus_index_biz.type = 1  # 私人知识库
            milvus_index_biz.user_id = userId
            milvus_index_biz.milvus_index = f"user_{userId}"
            milvus_index_biz.name = f"{self.name}的私人知识库"
            milvus_index_biz.description = f"{self.name}的私人知识库"
            await milvus_index_biz.create()

            return userId

class UserUpdateBiz(UserUpdateMdl):

    async def update(self, user_id: str):
        async with g.db_async_session() as session:
            updated_ids =  await db_async.update(
                session=session,
                model=User,
                data={
                    "name": self.name,
                    "age": self.age,
                    "role": self.role,
                    "collections": self.collections,
                },
                filter_by={"id": user_id},
            )

            await db_async.update(
                session=session,
                model=UserCollection,
                data={
                    "is_deleted": 1,
                },
                filter_by={"user_id": user_id},
            )
            userCollectionBiz = UserCollectionCreateBiz()
            if self.milvusIndexIdList and len(self.milvusIndexIdList) > 0:
                for milvus_index_id in self.milvusIndexIdList:
                    userCollectionBiz.user_id = user_id
                    userCollectionBiz.milvus_index_id = milvus_index_id
                    await userCollectionBiz.create()
            return updated_ids


class UserDeleteBiz(UserDeleteMdl):

    @staticmethod
    async def delete(user_id: str):
        async with g.db_async_session() as session:
            return await db_async.delete(
                session=session,
                model=User,
                filter_by={"id": user_id},
            )


class UserLoginBiz(UserLoginMdl):

    async def login(self):
        async with g.db_async_session() as session:
            data = await db_async.query_one(
                session=session,
                model=User,
                filter_by={"phone": self.phone},
            )
            if not data or not auth.verify_password(self.password, data.get("password")):
                return None
            new_jwt_key = auth.gen_jwt_key()
            token = auth.gen_jwt(
                payload={
                    "id": data.get("id"),
                    "phone": data.get("phone"),
                    "name": data.get("name"),
                    "age": data.get("age"),
                    "gender": data.get("gender"),
                },
                jwt_key=new_jwt_key,
                exp_minutes=24 * 60 * 30,
            )
            # 更新jwt_key
            await db_async.update(
                session=session,
                model=User,
                data={"jwt_key": new_jwt_key},
                filter_by={"phone": self.phone},
            )
            return token


class UserTokenBiz(UserTokenMdl):

    async def token(self):
        async with g.db_async_session() as session:
            data = await db_async.query_one(
                session=session,
                model=User,
                filter_by={"id": self.id},
            )
            if not data:
                return None
            new_jwt_key = auth.gen_jwt_key()
            token = auth.gen_jwt(
                payload={
                    "id": data.get("id"),
                    "phone": data.get("phone"),
                    "name": data.get("name"),
                    "age": data.get("age"),
                    "gender": data.get("gender"),
                },
                jwt_key=new_jwt_key,
                exp_minutes=self.exp_minutes,
            )
            # 更新jwt_key
            await db_async.update(
                session=session,
                model=User,
                data={"jwt_key": new_jwt_key},
                filter_by={"id": self.id},
            )
            return token
